package com.eliza.base.views.learn.animation

import androidx.compose.animation.core.AnimationVector1D
import androidx.compose.animation.core.AnimationVector2D
import androidx.compose.animation.core.Easing
import androidx.compose.animation.core.FastOutLinearInEasing
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.TwoWayConverter
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.animateValueAsState
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.keyframes
import androidx.compose.animation.core.repeatable
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp

object AnimationCustomizeX {
    @Composable
    fun Show() {
        var swi by remember {
            mutableIntStateOf(0)
        }
        Column {
            Button(onClick = { swi = (swi + 1) % 4 }) {
                Text(text = "ShapesAnimationX ${swi}")
            }
            when (swi) {
                0 -> AnimationSpecX()
                1 -> AnimationKeyframes()
                2 -> AnimationCustomDataType()
            }
        }
    }

    @Composable
    fun AnimationSpecX(modifier: Modifier = Modifier) {
        val enabled by remember {
            mutableStateOf(true)
        }
        val alpha: Float by animateFloatAsState(
            targetValue = if (enabled) 1f else 0.5f,
            // Configure the animation duration and easing.
            animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing),
            label = "alpha"
        )
        /*
        * 相比基于时长的 AnimationSpec 类型，spring 可以更流畅地处理中断，因为它可以在目标值在动画中变化时保证速度的连续性。
        * spring 用作很多动画 API（如 animate*AsState 和 updateTransition）的默认 AnimationSpec。
        * */
        val alphax: Float by animateFloatAsState(
            targetValue = if (enabled) 1f else 0.5f,
            // Configure the animation duration and easing.
            animationSpec = spring(
                dampingRatio = Spring.DampingRatioHighBouncy,
                stiffness = Spring.StiffnessMedium
            ),
            label = "alpha"
        )

        val value by animateFloatAsState(
            targetValue = 1f,
            animationSpec = tween(
                durationMillis = 300,//tween 在指定的 durationMillis 内使用缓和曲线在起始值和结束值之间添加动画效果
                delayMillis = 50,//delayMillis 来推迟动画的开始播放
                easing = LinearOutSlowInEasing
            ), label = "tween"
        )
    }

    @Composable
    fun AnimationKeyframes(modifier: Modifier = Modifier) {
        val value by animateFloatAsState(
            targetValue = 1f,
            animationSpec = keyframes {
                durationMillis = 375
                0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms
                0.2f at 15 using FastOutLinearInEasing // for 15-75 ms
                0.4f at 75 // ms
                0.4f at 225 // ms
            }
        )

        val valuex by animateFloatAsState(
            targetValue = 1f,
            animationSpec = repeatable(
                iterations = 3,
                animation = tween(durationMillis = 300),
                repeatMode = RepeatMode.Reverse
            )
        )
        val CustomEasing = Easing { fraction -> fraction * fraction }
        val values by animateFloatAsState(
            targetValue = 1f,
            animationSpec = infiniteRepeatable(
                // 使用 Easing 来调整动画的小数值。这样可让动画值加速和减速，而不是以恒定的速率移动。
                //小数是介于 0（起始值）和 1.0（结束值）之间的值，表示动画中的当前点。
                animation = tween(
                    durationMillis = 300,
                    easing = CustomEasing
                ),
                repeatMode = RepeatMode.Reverse
            )
        )
//        snap 是特殊的 AnimationSpec，它会立即将值切换到结束值。
//        您可以指定 delayMillis 来延迟动画播放的开始时间。
        val valueSnap by animateFloatAsState(
            targetValue = 1f,
            animationSpec = snap(delayMillis = 50)
        )
        //使用相应的 TwoWayConverter 即可将值转换为 AnimationVector
        val IntToVector: TwoWayConverter<Int, AnimationVector1D> =
            TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
    }

    @Composable
    fun AnimationCustomDataType(modifier: Modifier = Modifier) {
        data class MySize(val width: Dp, val height: Dp)

        val targetSize = MySize(1.dp, 2.dp)
        val animSize: MySize by animateValueAsState(
            targetSize,
            TwoWayConverter(
                convertToVector = { size: MySize ->
                    // Extract a float value from each of the `Dp` fields.
                    AnimationVector2D(size.width.value, size.height.value)
                },
                convertFromVector = { vector: AnimationVector2D ->
                    MySize(vector.v1.dp, vector.v2.dp)
                }
            ), label = "animSize"
        )
    }
}